package com.by.toolkitspring.handler;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.by.toolkit.consts.GlobalConst;
import com.by.toolkit.utils.SplitterUtil;
import com.by.toolkitspring.customizeannotation.AbstractByAnnotationContext;
import com.by.toolkitspring.customizeannotation.ByAnnotationProcessor;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
public class HandlerContext implements AbstractByAnnotationContext<Handler> {

    private static final Map<String, Class<?>> HANDLER_MAP = Maps.newHashMap();

    private static final Map<String, Class<?>> HANDLER_GENERICITY_T_CLASS_MAP = Maps.newHashMap();

    private static final Map<String, Class<?>> HANDLER_GENERICITY_R_CLASS_MAP = Maps.newHashMap();


    @Override
    public void receiveContext(List<ByAnnotationProcessor.CustomizeAnnotationInfo> infos) {
        if (CollectionUtils.isEmpty(infos)) {
            return;
        }

        HANDLER_MAP.putAll(infos.stream().collect(Collectors.toMap(i -> {
            Handler handler = (Handler) i.getAnnotationInfo();
            return SplitterUtil.UNDERSCORE_JOINER.join(handler.group(), handler.subCode(), handler.subCodeStr());
        }, ByAnnotationProcessor.CustomizeAnnotationInfo::getBeanClass)));

        HANDLER_GENERICITY_T_CLASS_MAP.putAll(infos.stream().collect(Collectors.toMap(
                i -> {
                    Handler handler = (Handler) i.getAnnotationInfo();
                    return SplitterUtil.UNDERSCORE_JOINER.join(handler.group(), handler.subCode(), handler.subCodeStr());
                },
                info -> ClassUtil.getTypeArgument(info.getBeanClass(), 0)))
        );

        HANDLER_GENERICITY_R_CLASS_MAP.putAll(infos.stream().collect(Collectors.toMap(
                i -> {
                    Handler handler = (Handler) i.getAnnotationInfo();
                    return SplitterUtil.UNDERSCORE_JOINER.join(handler.group(), handler.subCode(), handler.subCodeStr());
                },
                info -> ClassUtil.getTypeArgument(info.getBeanClass(), 1)))
        );
    }


    public AbstractHandlerInterface get(String group, Integer subCode) {
        Class<?> aClass = HANDLER_MAP.get(SplitterUtil.UNDERSCORE_JOINER.join(group, subCode, GlobalConst.MIN_INTEGER_STR));
        if (Objects.isNull(aClass)) {
            return null;
        }
        return (AbstractHandlerInterface) SpringUtil.getBean(aClass);
    }

    public Class<?> getGenericityTClass(String group, Integer subCode) {
        return HANDLER_GENERICITY_T_CLASS_MAP.get(SplitterUtil.UNDERSCORE_JOINER.join(group, subCode, GlobalConst.MIN_INTEGER_STR));
    }

    public Class<?> getGenericityRClass(String group, Integer subCode) {
        return HANDLER_GENERICITY_R_CLASS_MAP.get(SplitterUtil.UNDERSCORE_JOINER.join(group, subCode, GlobalConst.MIN_INTEGER_STR));
    }

    public AbstractHandlerInterface get(String group, String subCodeStr) {
        Class<?> aClass = HANDLER_MAP.get(SplitterUtil.UNDERSCORE_JOINER.join(group, GlobalConst.MIN_INTEGER_STR, subCodeStr));
        if (Objects.isNull(aClass)) {
            return null;
        }
        return (AbstractHandlerInterface) SpringUtil.getBean(aClass);
    }

    public Class<?> getGenericityTClass(String group, String subCodeStr) {
        return HANDLER_GENERICITY_T_CLASS_MAP.get(SplitterUtil.UNDERSCORE_JOINER.join(group, GlobalConst.MIN_INTEGER_STR, subCodeStr));
    }

    public Class<?> getGenericityRClass(String group, String subCodeStr) {
        return HANDLER_GENERICITY_R_CLASS_MAP.get(SplitterUtil.UNDERSCORE_JOINER.join(group, GlobalConst.MIN_INTEGER_STR, subCodeStr));
    }

}
